﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace PlanetSim.ParticleSimulator
{
    public class SimulationParameters
    {
        public float SmoothLength;                  // otherwise known as H
        public float SmoothLengthSquared;
        public float Stiffness;
        public float WPoly6Coefficient;             // the kernel function coefficient
        public float GradientWPoly6Coefficient;
        public float GradientWSpikyCoefficient;     
        public float GasConstant = 15f;
        public float RestDensityCoefficient = 50f; // affects how particles push eachother apart
        public float RestDensity;
        public float DampingCoefficient = 0.98f;
        public float VacuumDensity;
        public float InitialDensityCoefficient = 2f;
        public float InitialDensity;
        public Vector Gravity = new Vector(0, .5f);
        public float LaplacianWViscosityCoefficient;
        public float Viscosity = .15f;

        public float Width;
        public float Height;

        public static SimulationParameters BuildDefault(float width, float height)
        {
            SimulationParameters p = new SimulationParameters();
            p.SetSmoothLength(32);
            p.Width = width;
            p.Height = height;
            return p;
        }

        protected void SetSmoothLength(float smoothLength)
        {
            this.SmoothLength = smoothLength;
            this.SmoothLengthSquared = smoothLength * smoothLength;
            this.WPoly6Coefficient = 315.0f / (64.0f * (float)(Math.PI * Math.Pow(SmoothLength, 9)));
            this.GradientWPoly6Coefficient = -945.0f / (32.0f * (float)(Math.PI * Math.Pow(SmoothLength, 9)));
            this.GradientWSpikyCoefficient = -45.0f / (float)(Math.PI * Math.Pow(SmoothLength, 6));
            this.VacuumDensity = WPoly6(SmoothLengthSquared);
            this.InitialDensity = InitialDensityCoefficient * VacuumDensity;
            this.RestDensity = RestDensityCoefficient * VacuumDensity;
            this.LaplacianWViscosityCoefficient = 45.0f / (float)(Math.PI * Math.Pow(SmoothLength, 5));
        }

        public float WPoly6(float squareDifference)
        {
            return WPoly6Coefficient * (float)Math.Pow(squareDifference, 3);
        }

        public Vector GradientWPoly6(Vector r, float squareDifference)
        {
            return r * GradientWPoly6Coefficient * (float)Math.Pow(squareDifference, 2);
        }

        public Vector GradientWSpiky(Vector r, float length)
        {
            return r * (GradientWSpikyCoefficient / length) * (float)Math.Pow(SmoothLength - length, 2);
        }

        public float LaplacianWViscosity(float length)
        {
            return LaplacianWViscosityCoefficient * (1f - length / SmoothLength);
        }
    }
}
